/*-------------------------------------------------------------------------
 *
 * pg_proc.h
 *	  "过程" 系统目录 (pg_proc) 的定义
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/catalog/pg_proc.h
 *
 * NOTES
 *	  Catalog.pm 模块读取此文件并推导模式信息。
 *
 *-------------------------------------------------------------------------
 */
#ifndef PG_PROC_H
#define PG_PROC_H

#include "catalog/genbki.h"
#include "catalog/objectaddress.h"
#include "catalog/pg_proc_d.h"
#include "nodes/pg_list.h"

/* ----------------
 *		pg_proc 定义。 cpp 将其转换为
 *		typedef struct FormData_pg_proc
 * ----------------
 */
CATALOG(pg_proc,1255,ProcedureRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81,ProcedureRelation_Rowtype_Id) BKI_SCHEMA_MACRO
{
	Oid			oid;			/* oid */

	/* 过程名称 */
	NameData	proname;

	/* 包含此过程的命名空间的 OID */
	Oid			pronamespace BKI_DEFAULT(pg_catalog) BKI_LOOKUP(pg_namespace);

	/* 过程所有者 */
	Oid			proowner BKI_DEFAULT(POSTGRES) BKI_LOOKUP(pg_authid);

	/* pg_language 条目 OID */
	Oid			prolang BKI_DEFAULT(internal) BKI_LOOKUP(pg_language);

	/* 估计执行成本 */
	float4		procost BKI_DEFAULT(1);

	/* 估计输出行数 (如果 proretset) */
	float4		prorows BKI_DEFAULT(0);

	/* 可变数组的元素类型，如果不是可变则为 0 */
	Oid			provariadic BKI_DEFAULT(0) BKI_LOOKUP_OPT(pg_type);

	/* 此函数的规划器支持函数，或如果没有则为 0 */
	regproc		prosupport BKI_DEFAULT(0) BKI_LOOKUP_OPT(pg_proc);

	/* 见下方 PROKIND_ 类别 */
	char		prokind BKI_DEFAULT(f);

	/* 安全定义者 */
	bool		prosecdef BKI_DEFAULT(f);

	/* 是否是防泄漏功能? */
	bool		proleakproof BKI_DEFAULT(f);

	/* 对 NULLs 严格吗? */
	bool		proisstrict BKI_DEFAULT(t);

	/* 返回一个集合? */
	bool		proretset BKI_DEFAULT(f);

	/* 参见下面的 PROVOLATILE_ 类别 */
	char		provolatile BKI_DEFAULT(i);

	/* 参见下面的 PROPARALLEL_ 类别 */
	char		proparallel BKI_DEFAULT(s);

	/* number of arguments */
	/* 注意：不必在 pg_proc.dat 中给出；genbki.pl 将计算它 */
	int16		pronargs;

	/* 默认参数的数量 */
	int16		pronargdefaults BKI_DEFAULT(0);

	/* 结果类型的 OID */
	Oid			prorettype BKI_LOOKUP(pg_type);

	/*
	 * 可变长度字段从这里开始，但我们允许直接访问
	 * proargtypes
	 */

	/* 参数类型（不包括 OUT 参数） */
	oidvector	proargtypes BKI_LOOKUP(pg_type) BKI_FORCE_NOT_NULL;

#ifdef CATALOG_VARLEN

	/* 所有参数类型（如果仅为 IN 则为 NULL） */
	Oid			proallargtypes[1] BKI_DEFAULT(_null_) BKI_LOOKUP(pg_type);

	/* 参数模式（如果仅为 IN 则为 NULL） */
	char		proargmodes[1] BKI_DEFAULT(_null_);

	/* 参数名称（如果没有名称则为 NULL） */
	text		proargnames[1] BKI_DEFAULT(_null_);

	/* 参数默认值的表达式树列表（如果没有则为 NULL） */
	pg_node_tree proargdefaults BKI_DEFAULT(_null_);

	/* 要应用转换的类型 */
	Oid			protrftypes[1] BKI_DEFAULT(_null_) BKI_LOOKUP(pg_type);

	/* 过程源代码文本 */
	text		prosrc BKI_FORCE_NOT_NULL;

	/* 次要过程信息（可以为 NULL） */
	text		probin BKI_DEFAULT(_null_);

	/* 预解析的 SQL 函数主体 */
	pg_node_tree prosqlbody BKI_DEFAULT(_null_);

	/* 过程本地 GUC 设置 */
	text		proconfig[1] BKI_DEFAULT(_null_);

	/* 访问权限 */
	aclitem		proacl[1] BKI_DEFAULT(_null_);
#endif
} FormData_pg_proc;

/* ----------------
 *		Form_pg_proc 对应指向具有
 *		pg_proc 关系格式的元组的指针。
 * ----------------
 */
typedef FormData_pg_proc *Form_pg_proc;

DECLARE_TOAST(pg_proc, 2836, 2837);

DECLARE_UNIQUE_INDEX_PKEY(pg_proc_oid_index, 2690, ProcedureOidIndexId, on pg_proc using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index, 2691, ProcedureNameArgsNspIndexId, on pg_proc using btree(proname name_ops, proargtypes oidvector_ops, pronamespace oid_ops));

#ifdef EXPOSE_TO_CLIENT_CODE

/*
 * prokind 列的符号值
 */
#define PROKIND_FUNCTION 'f'
#define PROKIND_AGGREGATE 'a'
#define PROKIND_WINDOW 'w'
#define PROKIND_PROCEDURE 'p'

/*
 * provolatile 列的符号值：这些值指示一个函数的结果是否仅依赖于其显式参数的值，
 * 或者是否会因外部因素（如参数变量或
 * 表内容）而改变。注意：具有副作用的函数，如 setval()，
 * 必须标记为 volatile，以确保它们不会被优化掉，
 * 即使实际返回值不可更改。
 */
#define PROVOLATILE_IMMUTABLE	'i' /* 对于给定输入永远不改变 */
#define PROVOLATILE_STABLE		's' /* 在扫描过程中不改变 */
#define PROVOLATILE_VOLATILE	'v' /* 即使在扫描过程中也可能改变 */

/*
 * 并行列的符号值：这些指示一个函数是否可以安全地在并行后端运行，
 * 在并行时但必定在领导者中，或仅在非并行模式下运行。
 */
#define PROPARALLEL_SAFE		's' /* 可以在工作者或领导者中运行 */
#define PROPARALLEL_RESTRICTED	'r' /* 只能在并行领导者中运行 */
#define PROPARALLEL_UNSAFE		'u' /* 在并行模式下禁止使用 */

/*
 * proargmodes 列的符号值。请注意，这些必须与 parsenodes.h 中的
 * FunctionParameterMode 枚举相一致；我们在这里声明它们，以便从任何头文件中访问。
 */
#define PROARGMODE_IN		'i'
#define PROARGMODE_OUT		'o'
#define PROARGMODE_INOUT	'b'
#define PROARGMODE_VARIADIC 'v'
#define PROARGMODE_TABLE	't'

#endif							/* EXPOSE_TO_CLIENT_CODE */


extern ObjectAddress ProcedureCreate(const char *procedureName,
									 Oid procNamespace,
									 bool replace,
									 bool returnsSet,
									 Oid returnType,
									 Oid proowner,
									 Oid languageObjectId,
									 Oid languageValidator,
									 const char *prosrc,
									 const char *probin,
									 Node *prosqlbody,
									 char prokind,
									 bool security_definer,
									 bool isLeakProof,
									 bool isStrict,
									 char volatility,
									 char parallel,
									 oidvector *parameterTypes,
									 Datum allParameterTypes,
									 Datum parameterModes,
									 Datum parameterNames,
									 List *parameterDefaults,
									 Datum trftypes,
									 Datum proconfig,
									 Oid prosupport,
									 float4 procost,
									 float4 prorows);

extern bool function_parse_error_transpose(const char *prosrc);

extern List *oid_array_to_list(Datum datum);

#endif							/* PG_PROC_H */
